home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / pgpkey.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  13KB  |  583 lines

  1. /*
  2.  * Copyright (C) 1996,1997 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. /* WARNING!!!  WARNING!!!  WARNING!!!  WARNING!!!  WARNING!!!  WARNING!!!
  20.  *
  21.  * Legal for distribution in the U.S./Canada ONLY!  Exporting this file
  22.  * outside of the U.S./Canada may be in violation of ITAR regulations!
  23.  */
  24.  
  25. #include "mutt.h"
  26. #include "mutt_curses.h"
  27. #include "mutt_menu.h"
  28. #include "mime.h"
  29. #include "pgp.h"
  30.  
  31.  
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <stdlib.h>
  35. #include <unistd.h>
  36. #include <sys/stat.h>
  37. #include <sys/wait.h>
  38.  
  39. #ifdef _PGPPATH
  40.  
  41. static struct pgp_cache {
  42.   char *what;
  43.   char *dflt;
  44.   struct pgp_cache *next;
  45. } * id_defaults = NULL;
  46.  
  47. typedef struct
  48. {
  49.   KEYINFO *k;
  50.   PGPUID *a;
  51. } pgp_key_t;
  52.  
  53. static char trust_flags[] = "?- +";
  54.  
  55. static char *pgp_key_abilities(int flags)
  56. {
  57.   static char buff[3];
  58.   
  59.   if(!(flags & KEYFLAG_CANENCRYPT))
  60.     buff[0] = '-';
  61.   else if(flags & KEYFLAG_PREFER_SIGNING)
  62.     buff[0] = '.';
  63.   else
  64.     buff[0] = 'e';
  65.   
  66.   if(!(flags & KEYFLAG_CANSIGN))
  67.     buff[1] = '-';
  68.   else if(flags & KEYFLAG_PREFER_ENCRYPTION)
  69.     buff[1] = '.';
  70.   else
  71.     buff[1] = 's';
  72.   
  73.   buff[2] = '\0';
  74.   
  75.   return buff;
  76. }
  77.  
  78. static void pgp_entry (char *s, size_t l, MUTTMENU *menu, int num)
  79. {
  80.   pgp_key_t *KeyTable = (pgp_key_t *) menu->data;
  81.  
  82.   snprintf (s, l, "%4d %c%c %4d/0x%s %-4s %2s  %s",
  83.         num + 1,
  84.         (option(OPTPGPCHECKTRUST) ?
  85.          trust_flags[KeyTable[num].a->trust & 0x03] : ' '),
  86.         (option(OPTPGPCHECKTRUST) &&
  87.          (KeyTable[num].k->flags & KEYFLAG_CRITICAL) ?
  88.          'c' : ' '),
  89.         KeyTable[num].k->keylen, 
  90.         pgp_keyid(KeyTable[num].k),
  91.         KeyTable[num].k->algorithm, 
  92.         pgp_key_abilities(KeyTable[num].k->flags),
  93.         KeyTable[num].a->addr);
  94. }
  95.  
  96. static int pgp_search (MUTTMENU *m, regex_t *re, int n)
  97. {
  98.   char buf[LONG_STRING];
  99.   
  100.   pgp_entry (buf, sizeof (buf), m, n);
  101.   return (regexec (re, buf, 0, NULL, 0));
  102. }
  103.  
  104. static int pgp_compare (const void *a, const void *b)
  105. {
  106.   pgp_key_t *s = (pgp_key_t *) a;
  107.   pgp_key_t *t = (pgp_key_t *) b;
  108.  
  109.   return (strcasecmp (s->a->addr, t->a->addr));
  110. }
  111.  
  112. static char *pgp_select_key (LIST *keys, ADDRESS *p, const char *s)
  113. {
  114.   int keymax;
  115.   pgp_key_t *KeyTable;
  116.   MUTTMENU *menu;
  117.   LIST *a;
  118.   int i;  
  119.   int done = 0;
  120.   LIST *l;
  121.   char *id = NULL, helpstr[SHORT_STRING], buf[LONG_STRING];
  122.   char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
  123.   FILE *fp, *devnull;
  124.   pid_t thepid;
  125.   KEYINFO *info;
  126.   
  127.   
  128.   for (i = 0, l = keys; l; l = l->next)
  129.   {
  130.     int did_main_key = 0;
  131.     
  132.     info = (KEYINFO *) l->data;
  133.     a = info->address;
  134.    retry1:
  135.     for (; a; i++, a = a->next)
  136.       ;
  137.  
  138.     if(!did_main_key && info->flags & KEYFLAG_SUBKEY && info->mainkey)
  139.     {
  140.       did_main_key = 1;
  141.       a = info->mainkey->address;
  142.       goto retry1;
  143.     }
  144.   }
  145.     
  146.   if (i == 0) return NULL;
  147.  
  148.   keymax = i;
  149.   KeyTable = safe_malloc (sizeof (pgp_key_t) * i);
  150.  
  151.   for (i = 0, l = keys; l; l = l->next)
  152.   {
  153.     int did_main_key = 0;
  154.     info = (KEYINFO *)l->data;
  155.     a = info->address;
  156.    retry2:    
  157.     for (; a ; i++, a = a->next)
  158.     {
  159.       KeyTable[i].k = (KEYINFO *) l->data;
  160.       KeyTable[i].a = (PGPUID *)a->data;
  161.     }
  162.     if(!did_main_key && info->flags & KEYFLAG_SUBKEY && info->mainkey)
  163.     {
  164.       did_main_key = 1;
  165.       a = info->mainkey->address;
  166.       goto retry2;
  167.     }
  168.   }
  169.   
  170.   qsort (KeyTable, i, sizeof (pgp_key_t), pgp_compare);
  171.  
  172.   helpstr[0] = 0;
  173.   mutt_make_help (buf, sizeof (buf), "Exit  ", MENU_PGP, OP_EXIT);
  174.   strcat (helpstr, buf);
  175.   mutt_make_help (buf, sizeof (buf), "Select  ", MENU_PGP, 
  176.           OP_GENERIC_SELECT_ENTRY);
  177.   strcat (helpstr, buf);
  178.   mutt_make_help (buf, sizeof (buf), "Check key  ", MENU_PGP, OP_VERIFY_KEY);
  179.   strcat (helpstr, buf);
  180.   mutt_make_help (buf, sizeof (buf), "Help", MENU_PGP, OP_HELP);
  181.   strcat (helpstr, buf);
  182.  
  183.   menu = mutt_new_menu ();
  184.   menu->max = keymax;
  185.   menu->make_entry = pgp_entry;
  186.   menu->search = pgp_search;
  187.   menu->menu = MENU_PGP;
  188.   menu->help = helpstr;
  189.   menu->data = KeyTable;
  190.  
  191.   strfcpy (buf, "PGP keys matching ", sizeof (buf));
  192.   if (p)
  193.     rfc822_address (buf, sizeof (buf) - strlen (buf), p);
  194.   else
  195.     strcat (buf, s);
  196.   menu->title = buf;
  197.  
  198.   while (!done)
  199.   {
  200.     switch (mutt_menuLoop (menu))
  201.     {
  202.  
  203.       case OP_VERIFY_KEY:
  204.  
  205.         mutt_mktemp (tempfile);
  206.     if ((devnull = fopen ("/dev/null", "w")) == NULL)
  207.     {
  208.       mutt_perror ("Can't open /dev/null");
  209.       break;
  210.     }
  211.     if ((fp = safe_fopen (tempfile, "w")) == NULL)
  212.     {
  213.       fclose (devnull);
  214.       mutt_perror ("Can't create temporary file");
  215.       break;
  216.         }
  217.  
  218.     mutt_message ("Invoking PGP...");
  219.     
  220.         if((thepid = pgp_invoke_verify_key(NULL, NULL, NULL, -1,
  221.                        fileno(fp), fileno(devnull), 
  222.                        pgp_keyid(KeyTable[menu->current].k))) == -1)
  223.         {
  224.       mutt_perror ("Can't create filter");
  225.       unlink (tempfile);
  226.       fclose (fp);
  227.       fclose (devnull);
  228.     }
  229.  
  230.     mutt_wait_filter (thepid);
  231.     fclose (fp);
  232.     fclose (devnull);
  233.     mutt_clear_error ();
  234.         snprintf(cmd, sizeof(cmd), "Key ID: 0x%s", pgp_keyid(KeyTable[menu->current].k));
  235.     mutt_do_pager (cmd, tempfile, 0);
  236.     menu->redraw = REDRAW_FULL;
  237.     
  238.     break;
  239.  
  240.       case OP_VIEW_ID:
  241.         
  242.         mutt_message (KeyTable[menu->current].a->addr);
  243.         break;
  244.       
  245.       case OP_GENERIC_SELECT_ENTRY:
  246.  
  247.     if (option (OPTPGPCHECKTRUST) && 
  248.         (KeyTable[menu->current].a->trust & 0x03) < 3) 
  249.     {
  250.       char *s = "";
  251.       char buff[LONG_STRING];
  252.  
  253.       switch (KeyTable[menu->current].a->trust & 0x03)
  254.       {
  255.       case 0: s = "This ID's trust level is undefined."; break;
  256.       case 1: s = "This ID is not trusted."; break;
  257.       case 2: s = "This ID is only marginally trusted."; break;
  258.       }
  259.  
  260.       snprintf (buff, sizeof(buff), "%s Do you really want to use it?", s);
  261.  
  262.       if (mutt_yesorno (buff, 0) != 1)
  263.       {
  264.         mutt_clear_error ();
  265.         break;
  266.       }
  267.     }
  268.  
  269.     id = pgp_keyid(KeyTable[menu->current].k);
  270.     done = 1;
  271.     break;
  272.  
  273.       case OP_EXIT:
  274.  
  275.     id = NULL;
  276.     done = 1;
  277.     break;
  278.     }
  279.   }
  280.  
  281.   mutt_menuDestroy (&menu);
  282.   safe_free ((void **) &KeyTable);
  283.  
  284.   return (id);
  285. }
  286.  
  287. char *pgp_ask_for_key (const char *ringfile, KEYINFO *udb, char *tag, char *whatfor,
  288.                short abilities)
  289. {
  290.   KEYINFO *db;
  291.   char *key;
  292.   char resp[SHORT_STRING];
  293.   struct pgp_cache *l = NULL;
  294.  
  295.   db = udb ? udb : pgp_read_keyring(ringfile);
  296.  
  297.   resp[0] = 0;
  298.   if (whatfor) 
  299.   {
  300.  
  301.     for (l = id_defaults; l; l = l->next)
  302.       if (!strcasecmp (whatfor, l->what)) 
  303.       {
  304.     strcpy (resp, l->dflt);
  305.     break;
  306.       }
  307.   }
  308.  
  309.  
  310.   FOREVER
  311.   {
  312.     if (mutt_get_field (tag, resp, sizeof (resp), M_CLEAR) != 0)
  313.     {
  314.       if (!udb) pgp_closedb (db);
  315.       return NULL;
  316.     }
  317.     
  318.     if (whatfor) 
  319.     {
  320.       if (l)
  321.       {
  322.     safe_free ((void **)&l->dflt);
  323.     l->dflt = safe_strdup (resp);
  324.       } 
  325.       else
  326.       {
  327.     l = safe_malloc (sizeof (struct pgp_cache));
  328.     l->next = id_defaults;
  329.     id_defaults = l;
  330.     l->what = safe_strdup (whatfor);
  331.     l->dflt = safe_strdup (resp);
  332.       }
  333.     }
  334.  
  335.     if ((key = ki_getkeybystr (resp, db, abilities)))
  336.     {
  337.       key = safe_strdup (key);
  338.       if (!udb) pgp_closedb (db);
  339.       return (key);
  340.     }
  341.     BEEP ();
  342.   }
  343.   /* not reached */
  344. }
  345.  
  346. /* generate a public key attachment */
  347.  
  348. BODY *pgp_make_key_attachment (char * tempf)
  349. {
  350.   BODY *att;
  351.   char buff[LONG_STRING];
  352.   char tempfb[_POSIX_PATH_MAX];
  353.   char *id;
  354.   FILE *tempfp;
  355.   FILE *devnull;
  356.   struct stat sb;
  357.   pid_t thepid;
  358.  
  359.   unset_option (OPTPGPCHECKTRUST);
  360.   
  361.   if (!(id = pgp_ask_for_key (PgpPubring, NULL, "Please enter the key ID: ", NULL, 0)))
  362.     return NULL;
  363.  
  364.   if (!tempf) {
  365.     mutt_mktemp (tempfb);
  366.     tempf = tempfb;
  367.   }
  368.  
  369.   if ((tempfp = s